package spring.fox.processor;

import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import spring.fox.annotation.RpcReference;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import spring.fox.bean.RpcReferenceFactoryBean;
import spring.fox.config.RpcPropertyValues;

import java.lang.annotation.Annotation;
import java.lang.reflect.Member;

/**
 * @author cuichao
 * @Description: RpcReferenceBeanPostProcessor
 * @Date: create in 2021/3/8 23:29
 */
public class RpcReferenceBeanPostProcessor extends RpcAnnotationBeanPostProcessor<RpcReference> implements EnvironmentAware {

    public static final String BEAN_NAME = "rpcReferenceAnnotationBeanPostProcessor";

    private Environment environment;

    @Override
    protected String resolveBeanName(Member member, Class<?> injectType, Annotation annotation) {
        String beanName = injectType.getSimpleName() + "_RpcService";
        return beanName;
    }

    @Override
    protected BeanDefinition buildRpcBeanDefinition(Annotation annotation, Object bean, String beanName, Class<?> injectedType, String injectName) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(injectedType);
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        //setting property
        beanDefinition.setBeanClass(RpcReferenceFactoryBean.class);
        beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(annotation);
        MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
        builder.addPropertyValue(RpcReferenceFactoryBean.RPC_SERVICE_REGISTER_INTERFACE, injectedType);
        propertyValues.add(RpcReferenceFactoryBean.RPC_APPLICATION_CONTEXT_KEY, new RuntimeBeanReference(RpcReferenceFactoryBean.RPC_APPLICATION_CONTEXT_BEAN_NAME));
        propertyValues.addPropertyValues(new RpcPropertyValues(annotation, environment));
        return beanDefinition;
    }


    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}
